home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cdrecord-1.8.1 / lib / getargs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-25  |  18.0 KB  |  736 lines

  1. /* @(#)getargs.c    2.26 99/12/25 Copyright 1985, 1988, 1995 J. Schilling */
  2. #ifndef lint
  3. static    char sccsid[] =
  4.     "@(#)getargs.c    2.26 99/12/25 Copyright 1985, 1988, 1995 J. Schilling";
  5. #endif
  6. #define    NEW
  7. /*
  8.  *    Copyright (c) 1985, 1988, 1995 J. Schilling
  9.  *
  10.  *    1.3.88     Start implementation of release 2
  11.  */
  12. /*
  13.  *    Parse arguments on a command line.
  14.  *    Format string specifier (appearing directly after flag name):
  15.  *        ''    BOOL
  16.  *        '*'    string
  17.  *        '?'    char
  18.  *        '#'    number
  19.  *        '&'    call function
  20.  *        '+'    inctype        +++ NEU +++
  21.  */
  22. /*
  23.  * This program is free software; you can redistribute it and/or modify
  24.  * it under the terms of the GNU General Public License as published by
  25.  * the Free Software Foundation; either version 2, or (at your option)
  26.  * any later version.
  27.  *
  28.  * This program is distributed in the hope that it will be useful,
  29.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  30.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  31.  * GNU General Public License for more details.
  32.  *
  33.  * You should have received a copy of the GNU General Public License
  34.  * along with this program; see the file COPYING.  If not, write to
  35.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  36.  */
  37. /* LINTLIBRARY */
  38. #include <mconfig.h>
  39. #include <standard.h>
  40. #include <getargs.h>
  41. #include <ctype.h>
  42. #include <vadefs.h>
  43. #include <strdefs.h>
  44.  
  45. #define    NOARGS          0    /* No more args            */
  46. #define    NOTAFLAG      1    /* Not a flag type argument    */
  47. #define BADFLAG        (-1)    /* Not a valid flag argument    */
  48. #define BADFMT        (-2)    /* Error in format string    */
  49. #define NOTAFILE    (-3)    /* Seems to be a flag type arg    */
  50.  
  51.  
  52.     int    _getargs __PR((int *, char *const **, const char *,
  53.                             BOOL, va_list));
  54. LOCAL    int    dofile __PR((int *, char *const **, const char **));
  55. LOCAL    int    doflag __PR((int *, char *const **, const char *,
  56.                         const char *, BOOL, va_list));
  57. LOCAL    int    dosflags __PR((const char *, const char *, BOOL, va_list));
  58. LOCAL    int    checkfmt __PR((const char *));
  59. LOCAL    int    checkeql __PR((const char *));
  60.  
  61. LOCAL    va_list    va_dummy;
  62.  
  63. LOCAL    char    fmtspecs[] = "#?*&+"; 
  64.  
  65. #define    isfmtspec(c)        (strchr(fmtspecs, c) != NULL)
  66.  
  67. /*---------------------------------------------------------------------------
  68. |
  69. |    get flags until a non flag type argument is reached
  70. |
  71. +---------------------------------------------------------------------------*/
  72. /* VARARGS3 */
  73. #ifdef    PROTOTYPES
  74. int getargs(int *pac, char *const **pav, const char *fmt, ...)
  75. #else
  76. int getargs(pac, pav, fmt, va_alist)
  77.     int    *pac;
  78.     char    **pav[];
  79.     char    *fmt;
  80.     va_dcl
  81. #endif
  82. {
  83.     va_list    args;
  84.     int    ret;
  85.  
  86. #ifdef    PROTOTYPES
  87.     va_start(args, fmt);
  88. #else
  89.     va_start(args);
  90. #endif
  91.     ret = _getargs(pac, pav, fmt, TRUE, args);
  92.     va_end(args);
  93.     return (ret);
  94. }
  95.  
  96.  
  97. /*---------------------------------------------------------------------------
  98. |
  99. |    get all flags on the command line, do not stop on files
  100. |
  101. +---------------------------------------------------------------------------*/
  102. /* VARARGS3 */
  103. #ifdef    PROTOTYPES
  104. int getallargs(int *pac, char *const **pav, const char *fmt, ...)
  105. #else
  106. int getallargs(pac, pav, fmt, va_alist)
  107.     int    *pac;
  108.     char    **pav[];
  109.     char    *fmt;
  110.     va_dcl
  111. #endif
  112. {
  113.     va_list    args;
  114.     int    ret;
  115.  
  116. #ifdef    PROTOTYPES
  117.     va_start(args, fmt);
  118. #else
  119.     va_start(args);
  120. #endif
  121.     for (;; (*pac)--, (*pav)++) {
  122.         if ((ret = _getargs(pac, pav, fmt, TRUE, args)) != NOTAFLAG)
  123.             break;
  124.     }
  125.     va_end(args);
  126.     return (ret);
  127. }
  128.  
  129.  
  130. /*---------------------------------------------------------------------------
  131. |
  132. |    get next non flag type argument (i.e. a file)
  133. |
  134. +---------------------------------------------------------------------------*/
  135. int getfiles(pac, pav, fmt)
  136.     int        *pac;
  137.     char *const    *pav[];
  138.     const char    *fmt;
  139. {
  140.     return (_getargs(pac, pav, fmt, FALSE, va_dummy));
  141. }
  142.  
  143.  
  144. /*---------------------------------------------------------------------------
  145. |
  146. |    check args until the next non flag type argmument is reached
  147. |    *pac is decremented, *pav is incremented so that the
  148. |    non flag type argument is at *pav[0]
  149. |
  150. |    return code:
  151. |        NOARGS        no more args
  152. |        NOTAFLAG    not a flag type argument
  153. |        BADFLAG        a non-matching flag type argument
  154. |        BADFMT        bad syntax in format string
  155. |
  156. |
  157. +---------------------------------------------------------------------------*/
  158. /*LOCAL*/ int _getargs(pac, pav, fmt, setargs, args)
  159.     register int        *pac;
  160.     register char    *const    **pav;
  161.          const char    *fmt;
  162.         BOOL        setargs;
  163.         va_list        args;
  164. {
  165.     const     char    *argp;
  166.          int    ret;
  167.  
  168.  
  169.     for(; *pac > 0; (*pac)--, (*pav)++) {
  170.         argp = **pav;
  171.  
  172.         ret = dofile(pac, pav, &argp);
  173.  
  174.         if (ret != NOTAFILE)
  175.             return (ret);
  176.  
  177.         ret = doflag(pac, pav, argp, fmt, setargs, args);
  178.  
  179.         if (ret != NOTAFLAG)
  180.             return (ret);
  181.     }
  182.     return (NOARGS);
  183. }
  184.  
  185.  
  186. /*---------------------------------------------------------------------------
  187. |
  188. | check if *pargp is a file type argument
  189. |
  190. +---------------------------------------------------------------------------*/
  191. LOCAL int dofile(pac, pav, pargp)
  192.     register int        *pac;
  193.     register char *const    **pav;
  194.          const char    **pargp;
  195. {
  196.     register const char    *argp = *pargp;
  197.  
  198.  
  199.     if (argp[0] == '-') {
  200.         /*
  201.          * "-" is a special non flag type argument
  202.          *     that usually means take stdin instead of a named file
  203.          */
  204.         if (argp[1] == '\0')
  205.             return (NOTAFLAG);
  206.         /*
  207.          * "--" is a prefix to take the next argument
  208.          *    as non flag type argument
  209.          * NOTE: Posix requires "--" to indicate the end of the
  210.          *     flags on the command line. But we are currently not
  211.          *     Posix.
  212.          */
  213.         if (argp[1] == '-' && argp[2] == '\0') {
  214.             if (--(*pac) > 0) {
  215.                 (*pav)++;
  216.                 return (NOTAFLAG);
  217.             } else {
  218.                 return (NOARGS);
  219.             }
  220.         }
  221.     }
  222.  
  223.     /*
  224.      * now check if it may be flag type argument
  225.      * flag type arguments begin with a '-', a '+' or contain a '='
  226.      * i.e. -flag +flag or flag=
  227.      */
  228.     if (argp[0] != '-' && argp[0] != '+' && (!checkeql(argp)))
  229.         return (NOTAFLAG);
  230.  
  231.     return (NOTAFILE);
  232. }
  233.  
  234.  
  235. /*---------------------------------------------------------------------------
  236. |
  237. |    compare argp with the format string
  238. |    if a match is found store the result a la scanf in one of the
  239. |    arguments pointed to in the va_list
  240. |
  241. |    If setargs is FALSE, only check arguments for getfiles()
  242. |    in this case, va_list may be a dummy arg.
  243. |
  244. +---------------------------------------------------------------------------*/
  245. LOCAL int doflag(pac, pav, argp, fmt, setargs, oargs)
  246.         int        *pac;
  247.         char    *const    **pav;
  248.     register const char    *argp;
  249.     register const char    *fmt;
  250.         BOOL        setargs;
  251.         va_list        oargs;
  252. {
  253.     long    val;
  254.     int    singlecharflag    = 0;
  255.     BOOL    isspec;
  256.     BOOL    hasdash        = FALSE;
  257.     BOOL    doubledash    = FALSE;
  258.     BOOL    haseql        = checkeql(argp);
  259.     const char    *sargp;
  260.     const char    *sfmt    = fmt;
  261.     va_list    args;
  262.     char    *const    *spav    = *pav;
  263.     int        spac    = *pac;
  264.     void        *curarg    = (void *)0;
  265.  
  266.     /*
  267.      * flags beginning with '-' don't have to include the '-' in
  268.      * the format string.
  269.      * flags beginning with '+' have to include it in the format string.
  270.      */
  271.     if (argp[0] == '-') {
  272.         argp++;
  273.         hasdash = TRUE;
  274.         /*
  275.          * Implement legacy support for --longopt
  276.          * If we find a double dash, we do not look for combinations
  277.          * of boolean single char flags.
  278.          */
  279.         if (argp[0] == '-') {
  280.             argp++;
  281.             doubledash = TRUE;
  282.             /*
  283.              * Allow -- only for long options.
  284.              */
  285.             if (argp[1] == '\0') {
  286.                 return (BADFLAG);
  287.             }
  288.         }
  289.     }
  290.     sargp = argp;
  291.  
  292.     /*
  293.      * Initialize 'args' to the start of the argument list.
  294.      * I don't know any portable way to copy an arbitrary
  295.      * C object so I use a system-specific routine
  296.      * (probably a macro) from stdarg.h.  (Remember that
  297.      * if va_list is an array, 'args' will be a pointer
  298.      * and '&args' won't be what I would need for memcpy.)
  299.      * It is a system requirement for SVr4 compatibility
  300.      * to be able to do this assgignement. If your system
  301.      * defines va_list to be an array but does not define
  302.      * va_copy() you are lost.
  303.      * This is needed to make sure, that 'oargs' will not
  304.      * be clobbered.
  305.      */
  306.     va_copy(args, oargs);
  307.  
  308.     if (setargs)
  309.         curarg = va_arg(args, void *);
  310.  
  311.     /*
  312.      * check if the first flag in format string is a singlechar flag
  313.      */
  314.     if (fmt[1] == ',' || fmt[1] == '+' || fmt[1] == '\0')
  315.         singlecharflag++;
  316.     /*
  317.      * check the whole format string for a match
  318.      */
  319.     for(;;) {
  320.         for(;*fmt; fmt++,argp++) {
  321.             if (*fmt == '\\') {
  322.                 /*
  323.                  * Allow "#?*&+" to appear inside a flag.
  324.                  * NOTE: they must be escaped by '\\' only
  325.                  *     inside the the format string.
  326.                  */
  327.                 fmt++;
  328.                 isspec = FALSE;
  329.             } else {
  330.                 isspec = isfmtspec(*fmt);
  331.             }
  332.             /*
  333.              * If isspec is TRUE, the arg beeing checked starts
  334.              * like a valid flag. Argp now points to the rest.
  335.              */
  336.             if (isspec) {
  337.                 /*
  338.                  * If *argp is '+' and we are on the
  339.                  * beginning of the arg that is currently
  340.                  * checked, this cannot be an inc type flag.
  341.                  */
  342.                 if (*argp == '+' && argp == sargp)
  343.                     continue;
  344.                 /*
  345.                  * skip over to arg of flag
  346.                  */
  347.                 if (*argp == '=') {
  348.                     argp++;
  349.                 } else if (*argp != '\0' && haseql) {
  350.                     /*
  351.                      * Flag and arg are not separated by a
  352.                      * space.
  353.                      * Check here for:
  354.                      * xxxxx=yyyyy    match on '&'
  355.                      * Checked before:
  356.                      * abc=yyyyy    match on 'abc&'
  357.                      *         or     'abc*' 
  358.                      *         or     'abc#' 
  359.                      * We come here if 'argp' starts with
  360.                      * the same sequence as a valid flag
  361.                      * and contains an equal sign.
  362.                      * We have tested before if the text
  363.                      * before 'argp' matches exactly.
  364.                      * At this point we have no exact match
  365.                      * and we only allow to match
  366.                      * the special pattern '&'.
  367.                      * We need this e.g. for 'make'.
  368.                      * We allow any flag type argument to
  369.                      * match the format string "&" to set
  370.                      * up a function that handles all odd
  371.                      * stuff that getargs will not grok.
  372.                      * In addition, to allow getargs to be
  373.                      * used for CPP type flags we allow to
  374.                      * match -Dabc=xyz on 'D&'. Note that
  375.                      * Dabc=xyz will not match 'D&'.
  376.                      */
  377.                     if ((!hasdash && argp != sargp) || *fmt != '&')
  378.                         goto nextarg;
  379.                 }
  380.                 /*
  381.                  * *arpp == '\0' || !haseql
  382.                  * We come here if 'argp' starts with
  383.                  * the same sequence as a valid flag.
  384.                  * This will match on the following args:
  385.                  * -farg    match on 'f*'
  386.                  * -f12        match on 'f#'
  387.                  * +12        match on '+#'
  388.                  * -12        match on '#'
  389.                  * and all args that are separated from
  390.                  * their flags.
  391.                  * In the switch statement below, we check
  392.                  * if the text after 'argp' (if *argp != 0) or
  393.                  * the next arg is a valid arg for this flag.
  394.                   */
  395.                 break;
  396.             } else if (*fmt == *argp) {
  397.                 if (argp[1] == '\0' &&
  398.                     (fmt[1] == '\0' || fmt[1] == ',')) {
  399.  
  400.                     if (setargs)
  401.                         *((int *)curarg) = TRUE;
  402.  
  403.  
  404.                     return (checkfmt(fmt));/* XXX */
  405.                 }
  406.             } else {
  407.                 /*
  408.                  * skip over to next format identifier
  409.                  * & reset arg pointer
  410.                  */
  411.             nextarg:
  412.                 while (*fmt != ',' && *fmt != '\0') {
  413.                     /* function has extra arg on stack */
  414.                     if (*fmt == '&' && setargs)
  415.                         curarg = va_arg(args, void *);
  416.                     fmt++;
  417.                 }
  418.                 argp = sargp;
  419.                 break;
  420.             }
  421.         }
  422.         switch(*fmt) {
  423.  
  424.         case '\0':
  425.             /*
  426.              * Boolean type has been tested before.
  427.              */
  428.             if (singlecharflag && !doubledash &&
  429.                (val = dosflags(sargp, sfmt, setargs, oargs)) !=
  430.                                 BADFLAG)
  431.                 return (val);
  432.  
  433.  
  434.             return (BADFLAG);
  435.  
  436.         case ',':
  437.             fmt++;
  438.             if (fmt[1] == ',' || fmt[1] == '+' || fmt[1] == '\0')
  439.                 singlecharflag++;
  440.             if (setargs)
  441.                 curarg = va_arg(args, void *);
  442.             continue;
  443.  
  444.         case '*':
  445.             if (*argp == '\0') {
  446.                 if (*pac > 1) {
  447.                     (*pac)--;
  448.                     (*pav)++;
  449.                     argp = **pav;
  450.                 } else {
  451.                     return (BADFLAG);
  452.                 }
  453.             }
  454.             if (setargs)
  455.                 *((const char **)curarg) = argp;
  456.  
  457.  
  458.             return (checkfmt(fmt));
  459.  
  460.         case '?':
  461.             /*
  462.              * If more than one char arg, it
  463.              * cannot be a character argument.
  464.              */
  465.             if (argp[1] != '\0')
  466.                 goto nextchance;
  467.             if (setargs)
  468.                 *((char *)curarg) = *argp;
  469.  
  470.  
  471.             return (checkfmt(fmt));
  472.  
  473.         case '+':
  474.             /*
  475.              * inc type is similar to boolean,
  476.              * there is no arg in argp to convert.
  477.              */
  478.             if (*argp != '\0')
  479.                 goto nextchance;
  480.             if (fmt[1] == 'l' || fmt[1] == 'L') {
  481.                 if (setargs)
  482.                     *((long *)curarg) += 1;
  483.                 fmt++;
  484.             } else if (fmt[1] == 's' || fmt[1] == 'S') {
  485.                 if (setargs)
  486.                     *((short *)curarg) += 1;
  487.                 fmt++;
  488.             } else {
  489.                 if (fmt[1] == 'i' || fmt[1] == 'I')
  490.                     fmt++;
  491.                 if (setargs)
  492.                     *((int *)curarg) += 1;
  493.             }
  494.  
  495.  
  496.             return (checkfmt(fmt));
  497.  
  498.         case '#':
  499.             if (*argp == '\0') {
  500.                 if (*pac > 1) {
  501.                     (*pac)--;
  502.                     (*pav)++;
  503.                     argp = **pav;
  504.                 } else {
  505.                     return (BADFLAG);
  506.                 }
  507.             }
  508.             if (*astol(argp, &val) != '\0') {
  509.                 /*
  510.                  * arg is not a valid number!
  511.                  * go to next format in the format string
  512.                  * and check if arg matches any other type
  513.                  * in the format specs.
  514.                  */
  515.             nextchance:
  516.                 while(*fmt != ',' && *fmt != '\0') {
  517.                     if (*fmt == '&' && setargs)
  518.                         curarg = va_arg(args, void *);
  519.                     fmt++;
  520.                 }
  521.                 argp = sargp;
  522.                 *pac = spac;
  523.                 *pav = spav;
  524.                 continue;
  525.             }
  526.             if (fmt[1] == 'l' || fmt[1] == 'L') {
  527.                 if (setargs)
  528.                     *((long *)curarg) = val;
  529.                 fmt++;
  530.             } else if (fmt[1] == 's' || fmt[1] == 'S') {
  531.                 if (setargs)
  532.                     *((short *)curarg) = val;
  533.                 fmt++;
  534.             } else {
  535.                 if (fmt[1] == 'i' || fmt[1] == 'I')
  536.                     fmt++;
  537.                 if (setargs)
  538.                     *((int *)curarg) = val;
  539.             }
  540.  
  541.             return (checkfmt(fmt));
  542.  
  543.         case '&':
  544.             if (*argp == '\0') {
  545.                 if (*pac > 1) {
  546.                     (*pac)--;
  547.                     (*pav)++;
  548.                     argp = **pav;
  549.                 } else {
  550.                     return (BADFLAG);
  551.                 }
  552.             }
  553.  
  554.             if ((val = checkfmt(fmt)) != NOTAFLAG)
  555.                 return (val);
  556.  
  557.             if (setargs) {
  558.                 int    ret;
  559.                 void    *funarg = va_arg(args, void *);
  560.  
  561.                 ret = ((*(getargfun)curarg) (argp, funarg));
  562.                 if (ret != NOTAFILE)
  563.                     return (ret);
  564.                 fmt++;
  565.             } else {
  566.                 return (val);
  567.             }
  568.             /*
  569.              * Called function returns NOTAFILE: try next format.
  570.              */
  571.         }
  572.     }
  573. }
  574.  
  575.  
  576. /*---------------------------------------------------------------------------
  577. |
  578. |    parse args for combined single char flags
  579. |
  580. +---------------------------------------------------------------------------*/
  581. typedef struct {
  582.     void    *curarg;
  583.     short    count;
  584.     char    c;
  585.     char    type;
  586. } sflags;
  587.  
  588. LOCAL int dosflags(argp, fmt, setargs, oargs)
  589.     register const char    *argp;
  590.     register const char    *fmt;
  591.         BOOL        setargs;
  592.         va_list        oargs;
  593. {
  594. #define    MAXSF    32
  595.          sflags    sf[MAXSF];
  596.          va_list args;
  597.     register sflags    *rsf    = sf;
  598.     register int    nsf    = 0;
  599.     register const char *p    = argp;
  600.     register int    i;
  601.     register void    *curarg = (void *)0;
  602.  
  603.     /*
  604.      * Initialize 'args' to the start of the argument list.
  605.      * I don't know any portable way to copy an arbitrary
  606.      * C object so I use a system-specific routine
  607.      * (probably a macro) from stdarg.h.  (Remember that
  608.      * if va_list is an array, 'args' will be a pointer
  609.      * and '&args' won't be what I would need for memcpy.)
  610.      * It is a system requirement for SVr4 compatibility
  611.      * to be able to do this assgignement. If your system
  612.      * defines va_list to be an array but does not define
  613.      * va_copy() you are lost.
  614.      * This is needed to make sure, that 'oargs' will not
  615.      * be clobbered.
  616.      */
  617.     va_copy(args, oargs);
  618.  
  619.     if (setargs)
  620.         curarg = va_arg(args, void *);
  621.  
  622.     while (*p) {
  623.         for (i=0; i < nsf; i++) {
  624.             if (rsf[i].c == *p)
  625.                 break;
  626.         }
  627.         if (i >= MAXSF)
  628.             return (BADFLAG);
  629.         if (i == nsf) {
  630.             rsf[i].curarg = (void *)0;
  631.             rsf[i].count = 0;
  632.             rsf[i].c = *p;
  633.             rsf[i].type = (char)-1;
  634.             nsf++;
  635.         }
  636.         rsf[i].count++;
  637.         p++;
  638.     }
  639.  
  640.     while (*fmt) {
  641.         if (!isfmtspec(*fmt) &&
  642.             (fmt[1] == ',' || fmt[1] == '+' || fmt[1] == '\0') &&
  643.              strchr(argp, *fmt)) {
  644.             for (i=0; i < nsf; i++) {
  645.                 if (rsf[i].c == *fmt) {
  646.                     if (fmt[1] == '+') {
  647.                         fmt++;
  648.                         if (fmt[1] == ',' ||
  649.                             fmt[1] == '\0') {
  650.                             rsf[i].type = 'i';
  651.                         } else {
  652.                             rsf[i].type = fmt[1];
  653.                         }
  654.                     } else {
  655.                         rsf[i].type = fmt[1];
  656.                     }
  657.                     rsf[i].curarg = curarg;
  658.                     break;
  659.                 }
  660.             }
  661.         }
  662.         while (*fmt != ',' && *fmt != '\0') {
  663.             /* function has extra arg on stack */
  664.             if (*fmt == '&' && setargs)
  665.                 curarg = va_arg(args, void *);
  666.             fmt++;
  667.         }
  668.         if (*fmt != '\0')
  669.             fmt++;
  670.  
  671.         if (setargs)
  672.             curarg = va_arg(args, void *);
  673.     }
  674.     for (i=0; i < nsf; i++) {
  675.         if (rsf[i].type == (char)-1)
  676.             return (BADFLAG);
  677.         if (rsf[i].curarg) {
  678.             if (rsf[i].type == ',' || rsf[i].type == '\0') {
  679.                 *((int *)rsf[i].curarg) = TRUE;
  680.             } else if (rsf[i].type == 'i' || rsf[i].type == 'I') {
  681.                 *((int *)rsf[i].curarg) += rsf[i].count;
  682.             } else if (rsf[i].type == 'l' || rsf[i].type == 'L') {
  683.                 *((long *)rsf[i].curarg) += rsf[i].count;
  684.             } else if (rsf[i].type == 's' || rsf[i].type == 'S') {
  685.                 *((short *)rsf[i].curarg) += rsf[i].count;
  686.             } else {
  687.                 return (BADFLAG);
  688.             }
  689.         }
  690.     }
  691.     return (NOTAFLAG);
  692. }
  693.  
  694. /*---------------------------------------------------------------------------
  695. |
  696. |    If the next format character is a comma or the string delimiter,
  697. |    there are no invalid format specifiers. Return success.
  698. |    Otherwise raise the getarg_bad_format condition.
  699. |
  700. +---------------------------------------------------------------------------*/
  701. LOCAL int checkfmt(fmt)
  702.     const char    *fmt;
  703. {
  704.     char    c;
  705.  
  706.     c = *(++fmt);    /* non constant expression */
  707.  
  708.  
  709.     if (c == ',' || c == '\0') {
  710.         return (NOTAFLAG);
  711.     } else {
  712.         raisecond("getarg_bad_format", (long)fmt);
  713.         return (BADFMT);
  714.     }
  715. }
  716.  
  717. /*---------------------------------------------------------------------------
  718. |
  719. |    Parse the string as long as valid characters can be found.
  720. |    Valid flag identifiers are chosen from the set of
  721. |    alphanumeric characters, '-' and '_'.
  722. |    If the next character is an equal sign the string
  723. |    contains a valid flag identifier.
  724. |
  725. +---------------------------------------------------------------------------*/
  726. static int checkeql(str)
  727.     register const char *str;
  728. {
  729.     register unsigned char c;
  730.  
  731.     for (c = (unsigned char)*str;
  732.                 isalnum(c) || c == '_' || c == '-'; c = *str++)
  733.         ;
  734.     return (c == '=');
  735. }
  736.